<template>
  <div class="app-container">
    <div class="filter-container">
      <el-form :inline="true" class="form-inline">
        <el-form-item label="平台名称" size="mini">
          <el-select v-model="listQuery.platformName" placeholder="平台名称" style="width: 150px" class="filter-item" @change="handleGetEnums" >
            <el-option v-for="item in platformOptions" :key="item.name" :label="item.name===''?'全部':item.describe+'('+item.name+')'" :value="item.name===''?'':item.name"/>
          </el-select>
        </el-form-item>
        <el-form-item label="用户信息" size="mini">
          <el-select v-model="listQuery.userInfoType" placeholder="信息类型" default-first-option filterable clearable allow-create style="width: 120px" class="filter-item">
            <el-option v-for="item in userInfoTypeOptions" :key="item" :label="item" :value="item"/>
          </el-select>
          <el-input v-model="listQuery.userInfoValue" placeholder="用户信息" style="width: 150px;" class="filter-item" />
        </el-form-item>
        <el-form-item label="客户端" size="mini">
          <el-select v-model="listQuery.clientName" placeholder="客户端" default-first-option filterable clearable allow-create class="filter-item" style="width: 150px">
            <el-option v-for="item in clientNameOptions" :key="item" :label="item" :value="item"/>
          </el-select>
        </el-form-item>
        <el-form-item label="模块" size="mini">
          <el-select v-model="listQuery.serviceCategory" placeholder="模块" default-first-option filterable clearable allow-create class="filter-item" style="width: 150px">
            <el-option v-for="item in serviceCategoryOptions" :key="item" :label="item" :value="item"/>
          </el-select>
        </el-form-item>
        <el-form-item label="服务" size="mini">
          <el-select v-model="listQuery.serviceName" placeholder="服务" default-first-option filterable clearable allow-create class="filter-item" style="width: 150px">
            <el-option v-for="item in serviceNameOptions" :key="item" :label="item" :value="item"/>
          </el-select>
        </el-form-item>
        <el-form-item label="方法" size="mini">
          <el-select v-model="listQuery.methodName" placeholder="方法" default-first-option filterable clearable allow-create class="filter-item" style="width: 150px">
            <el-option v-for="item in methodNameOptions" :key="item" :label="item" :value="item"/>
          </el-select>
        </el-form-item>
        <br>
        <el-form-item label="部署环境" size="mini">
          <el-select v-model="listQuery.env" placeholder="部署环境" style="width: 150px" class="filter-item" @change="handleGetEnums" >
            <el-option v-for="item in envOptions" :key="item" :label="item" :value="item"/>
          </el-select>
        </el-form-item>
        <el-form-item label="日期范围" size="mini">
          <el-date-picker
            v-model="dateRange"
            :picker-options="pickerOptions"
            type="datetimerange"
            range-separator="至"
            start-placeholder="开始日期"
            end-placeholder="结束日期"
            class="filter-item"
            value-format="yyyy-MM-dd HH:mm:ss"
          />
        </el-form-item>
        <el-form-item label="类型" size="mini">
          <el-select v-model="listQuery.rpcType" placeholder="类型" clearable style="width: 120px" class="filter-item">
            <el-option v-for="item in rpcTypeOptions" :key="item" :label="item" :value="item"/>
          </el-select>
        </el-form-item>
        <el-form-item label="结果" size="mini">
          <el-select v-model="listQuery.result" placeholder="结果" clearable style="width: 120px" class="filter-item">
            <el-option v-for="item in resultOptions" :key="item" :label="item" :value="item"/>
          </el-select>
        </el-form-item>

        <el-form-item label="耗时" size="mini">
          <el-input v-model="listQuery.runTimeMin" style="width: 80px;" class="filter-item" clearable/>
        </el-form-item>
        <el-form-item label="至" size="mini">
          <el-input v-model="listQuery.runTimeMax" style="width: 80px;" class="filter-item" clearable/>
        </el-form-item>
        <el-form-item label="毫秒" size="mini"/>
        <br>
        <el-form-item label="ClientIP" size="mini">
          <el-input v-model="listQuery.clientIp" placeholder="ClientIp" style="width: 150px;" class="filter-item" clearable/>
        </el-form-item>
        <el-form-item label="ServerIp" size="mini">
          <el-input v-model="listQuery.serverIp" placeholder="ServerIp" style="width: 150px;" class="filter-item" clearable/>
        </el-form-item>

        <el-form-item label="入参" size="mini">
          <el-input v-model="listQuery.paramIn" style="width: 150px;" class="filter-item" clearable/>
        </el-form-item
        >
        <el-form-item label="出参" size="mini">
          <el-input v-model="listQuery.paramOut" style="width: 150px;" class="filter-item" clearable/>
        </el-form-item>

        <el-form-item label="入参大小" size="mini">
          <el-input v-model="listQuery.requestSizeMin" style="width: 60px;" class="filter-item" clearable/>
        </el-form-item>
        <el-form-item label="至" size="mini">
          <el-input v-model="listQuery.requestSizeMax" style="width: 60px;" class="filter-item" clearable/>
        </el-form-item>
        <el-form-item label="KB" size="mini"/>

        <el-form-item label="出参大小" size="mini">
          <el-input v-model="listQuery.responseSizeMin" style="width: 60px;" class="filter-item"/>
        </el-form-item>
        <el-form-item label="至" size="mini">
          <el-input v-model="listQuery.responseSizeMax" style="width: 60px;" class="filter-item"/>
        </el-form-item>
        <el-form-item label="KB" size="mini"/>

        <br>
        <el-form-item label="调用链ID" size="mini">
          <el-input ref="traceId" v-model="listQuery.traceId" placeholder="调用链ID" style="width: 350px;" class="filter-item" clearable @clear="handleClearTraceId"/>
        </el-form-item>
        <el-form-item label="rpcId" size="mini">
          <el-input v-model="listQuery.rpcId" placeholder="rpcId" style="width: 100px;" class="filter-item" clearable/>
        </el-form-item>

        <el-button v-waves class="filter-item" type="primary" icon="el-icon-search" size="mini" @click="handleQueryTraceInfo">查询</el-button>
        <el-button v-waves v-if="isSingleTrace" class="filter-item" type="success" icon="el-icon-tickets" size="mini" @click="displaySequence">显示时序图</el-button>

        <el-dropdown trigger="click" style="float: right;">
          <el-button size="mini" type="info">
            显示列<i class="el-icon-caret-bottom el-icon--right"/>
          </el-button>
          <el-dropdown-menu slot="dropdown">
            <el-checkbox v-model="display.platformName" class="drop-checkbox">平台名称</el-checkbox>
            <el-checkbox v-model="display.traceId" class="drop-checkbox">traceId</el-checkbox>
            <el-checkbox v-model="display.phone" class="drop-checkbox">phone</el-checkbox>
            <el-checkbox v-model="display.realName" class="drop-checkbox">realName</el-checkbox>
            <el-checkbox v-model="display.userId" class="drop-checkbox">userId</el-checkbox>
            <el-checkbox v-model="display.customerId" class="drop-checkbox">customerId</el-checkbox>
            <el-checkbox v-model="display.env" class="drop-checkbox">环境</el-checkbox>
            <el-checkbox v-model="display.clientName" class="drop-checkbox">客户端</el-checkbox>
            <el-checkbox v-model="display.serviceCategory" class="drop-checkbox">模块</el-checkbox>
            <el-checkbox v-model="display.serviceName" class="drop-checkbox">服务</el-checkbox>
            <el-checkbox v-model="display.methodName" class="drop-checkbox">方法</el-checkbox>
            <el-checkbox v-model="display.requestDateTime" class="drop-checkbox">请求时间</el-checkbox>
            <el-checkbox v-model="display.clientHost" class="drop-checkbox">ClientIp</el-checkbox>
            <el-checkbox v-model="display.serverHost" class="drop-checkbox">ServerIp</el-checkbox>
            <el-checkbox v-model="display.rpcType" class="drop-checkbox">类型</el-checkbox>
            <el-checkbox v-model="display.result" class="drop-checkbox">状态</el-checkbox>
            <el-checkbox v-model="display.requestSize" class="drop-checkbox">流量</el-checkbox>
            <el-checkbox v-model="display.runTime" class="drop-checkbox">耗时</el-checkbox>
            <el-checkbox v-model="display.timeline" class="drop-checkbox">时间线</el-checkbox>
          </el-dropdown-menu>
        </el-dropdown>
      </el-form>
    </div>

    <tree-table v-loading="listLoading" ref="treeTable" :data="data" :eval-func="func" :eval-args="args" :expand-all="expandAll" :row-click-func="handleRowClick" height="550" size="mini">
      <el-table-column v-if="display.platformName" label="平台名称" >
        <template slot-scope="scope">
          <span>{{ scope.row.platformName }}</span>
        </template>
      </el-table-column>
      <el-table-column v-if="display.traceId" label="traceId" width="240">
        <template slot-scope="scope">
          <span>{{ scope.row.traceId }}</span>
        </template>
      </el-table-column>
      <el-table-column v-if="display.phone" label="phone" width="120">
        <template slot-scope="scope">
          <span>{{ scope.row.userInfo!= undefined?scope.row.userInfo.phone:'' }}</span>
        </template>
      </el-table-column>
      <el-table-column v-if="display.realName" label="realName" width="120">
        <template slot-scope="scope">
          <span>{{ scope.row.userInfo!= undefined?scope.row.userInfo.realName:'' }}</span>
        </template>
      </el-table-column>
      <el-table-column v-if="display.userId" label="userId" width="120">
        <template slot-scope="scope">
          <span>{{ scope.row.userInfo!= undefined?scope.row.userInfo.userId:'' }}</span>
        </template>
      </el-table-column>
      <el-table-column v-if="display.customerId" label="customerId" width="120">
        <template slot-scope="scope">
          <span>{{ scope.row.userInfo!= undefined?scope.row.userInfo.customerId:'' }}</span>
        </template>
      </el-table-column>
      <el-table-column v-if="display.env" label="环境">
        <template slot-scope="scope">
          <span>{{ scope.row.env }}</span>
        </template>
      </el-table-column>
      <el-table-column v-if="display.clientName" label="客户端">
        <template slot-scope="scope">
          <span>{{ scope.row.clientName }}</span>
        </template>
      </el-table-column>
      <el-table-column v-if="display.serviceCategory" label="模块" width="120">
        <template slot-scope="scope">
          <span>{{ scope.row.serviceCategory }}</span>
        </template>
      </el-table-column>
      <el-table-column v-if="display.serviceName" label="服务" width="200">
        <template slot-scope="scope">
          <span>{{ scope.row.serviceName }}</span>
        </template>
      </el-table-column>
      <el-table-column v-if="display.methodName" label="方法" width="200">
        <template slot-scope="scope">
          <span>{{ scope.row.methodName }}</span>
        </template>
      </el-table-column>
      <el-table-column v-if="display.requestDateTime" label="时间" width="200">
        <template slot-scope="scope">
          <span>{{ scope.row.requestDateTime }}</span>
        </template>
      </el-table-column>
      <el-table-column v-if="display.clientHost" label="ClientIp" width="120">
        <template slot-scope="scope">
          <span>{{ scope.row.clientHost }}</span>
        </template>
      </el-table-column>
      <el-table-column v-if="display.serverHost" label="ServerIp" width="200">
        <template slot-scope="scope">
          <span>{{ scope.row.serverHost }}</span>
        </template>
      </el-table-column>
      <el-table-column v-if="display.rpcType" label="类型">
        <template slot-scope="scope">
          <span>{{ scope.row.rpcType }}</span>
        </template>
      </el-table-column>
      <el-table-column v-if="display.result" label="状态" width="90">
        <template slot-scope="scope">
          <el-tag v-if="scope.row.result==='OK'" type="success">{{ scope.row.result }}</el-tag>
          <el-tag v-if="scope.row.result==='ERROR'" type="danger">{{ scope.row.result }}</el-tag>
        </template>
      </el-table-column>
      <el-table-column label="入/出参" >
        <template slot-scope="scope">
          <el-button type="primary" size="mini" class="tag" style="margin: 0px" @click="displayParametersJson(scope.row)">参</el-button>
          <el-button type="success" size="mini" class="tag" style="margin: 0px" @click="displayJavaLog(scope.row)">日</el-button>
        </template>
      </el-table-column>
      <el-table-column v-if="display.requestSize" label="流量">
        <template slot-scope="scope">
          <span>{{ calTrafficSize(scope.row) }}</span>
        </template>
      </el-table-column>
      <el-table-column v-if="display.runTime" label="耗时">
        <template slot-scope="scope">
          <span>{{ scope.row.runTime+'ms' }}</span>
        </template>
      </el-table-column>
      <el-table-column v-if="display.timeline" label="时间线" width="200px">
        <template v-if="isSingleTrace===true" slot-scope="scope">
          <el-tooltip :content="scope.row.runTime+'ms'" effect="dark" placement="left">
            <div class="processContainer">
              <div
                :style="{ width:scope.row._width * 200+'px',
                          height:12+'px',
                          background:scope.row.runTime>500?'rgba(233,0,0,.5)':'rgba(0,0,233,0.5)',
                          marginLeft:scope.row._marginLeft * 200+'px' }"
                class="process">
                <span style="display:inline-block"/>
              </div>
            </div>
          </el-tooltip>
        </template>
      </el-table-column>
    </tree-table>
    <pagination v-show="total>0" :total="total" :page="listQuery.pageNum" :limit="listQuery.pageSize" layout="total, sizes, prev, pager, next" @pagination="handlePageChange" />

    <el-dialog :visible.sync="paramsVisible" title="入参出参">
      <el-form>
        <el-form-item label="入参:" >
          <el-input
            :autosize="{ minRows: 10,maxRows: 10}"
            v-model="parameterInJson"
            type="textarea"
            placeholder=""/>
        </el-form-item>
        <el-form-item label="出参:" >
          <el-input
            :autosize="{ minRows: 10,maxRows: 10}"
            v-model="parameterOutJson"
            type="textarea"
            placeholder=""/>
        </el-form-item>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button type="primary" @click="paramsVisible = false">确 定</el-button>
      </div>
    </el-dialog>

    <el-dialog :title="logTraceTableTitle" :visible.sync="logTraceVisible" top="2vh">
      <el-table :data="logTraceData" :border="true">
        <el-table-column property="@timestamp" label="time" width="180"/>
        <el-table-column property="level" label="level" width="80"/>
        <el-table-column property="location.class" label="class" width="120"/>
        <el-table-column property="location.method" label="method" width="120"/>
        <el-table-column property="message" label="message" />
      </el-table>
    </el-dialog>
    <div ref="diagramContainer" class="diagramContainer" @click="handleCloseDiagram" >
      <div id="diagram" ref="diagram" @click="handleCloseDiagram"/>
    </div>
  </div>
</template>

<script>
import TreeTable from '@/components/TreeTable'
import treeToArray from './customEval'
import waves from '@/directive/waves'
import Pagination from '@/components/Pagination'
import { getEnums, queryTraceInfo, queryJavaLog } from '@/api/console'
export default {
  name: 'Console',
  directives: { waves },
  components: { TreeTable, Pagination },
  data() {
    return {
      display: {
        platformName: false,
        traceId: false,
        phone: false,
        realName: false,
        userId: false,
        customerId: false,
        env: true,
        clientName: true,
        serviceCategory: false,
        serviceName: true,
        methodName: true,
        requestDateTime: true,
        clientHost: false,
        serverHost: false,
        rpcType: true,
        result: true,
        requestSize: true,
        runTime: true,
        timeline: true
      },
      listLoading: false,
      listQuery: {
        pageNum: 1,
        pageSize: 10,
        platformName: this.$store.getters.platforms[0].name,
        userInfoType: '',
        userInfoValue: '',
        clientName: '',
        serviceCategory: '',
        serviceName: '',
        methodName: '',
        env: '',
        fromDate: '',
        toDate: '',
        runTimeMin: '',
        runTimeMax: '',
        clientIp: '',
        serverIp: '',
        paramIn: '',
        paramOut: '',
        requestSizeMin: '',
        requestSizeMax: '',
        responseSizeMin: '',
        responseSizeMax: '',
        traceId: '',
        rpcId: '',
        sort: '+id'
      },
      total: 0,
      dateRange: undefined,
      platformOptions: this.$store.getters.platforms,
      envOptions: ['product', 'dev', 'test', 'pre'],
      userInfoTypeOptions: undefined,
      clientNameOptions: undefined,
      serviceCategoryOptions: undefined,
      serviceNameOptions: undefined,
      methodNameOptions: undefined,
      rpcTypeOptions: undefined,
      resultOptions: undefined,
      pickerOptions: {
        shortcuts: [{
          text: '最近1天',
          onClick(picker) {
            const end = new Date()
            const start = new Date()
            start.setTime(start.getTime() - 3600 * 1000 * 24 * 1)
            picker.$emit('pick', [start, end])
          }
        }, {
          text: '最近3天',
          onClick(picker) {
            const end = new Date()
            const start = new Date()
            start.setTime(start.getTime() - 3600 * 1000 * 24 * 3)
            picker.$emit('pick', [start, end])
          }
        }, {
          text: '最近7天',
          onClick(picker) {
            const end = new Date()
            const start = new Date()
            start.setTime(start.getTime() - 3600 * 1000 * 24 * 7)
            picker.$emit('pick', [start, end])
          }
        }]
      },
      func: treeToArray,
      expandAll: true,
      data: undefined,
      args: [null, null, 'runTime'],
      paramsVisible: false,
      parameterInJson: undefined,
      parameterOutJson: undefined,
      logTraceVisible: false,
      logTraceData: undefined,
      logTraceTableTitle: undefined,
      isSingleTrace: false,
      sequenceDiagramVisible: false
    }
  },
  created() {
    this.handleGetEnums()
  },
  methods: {
    handleGetEnums() {
      this.listLoading = true
      if (this.listQuery.env === '') {
        if (process.env.ENV_CONFIG === 'dev') {
          this.listQuery.env = 'dev'
        } else if (process.env.ENV_CONFIG === 'prod') {
          this.listQuery.env = 'product'
        }
      }
      getEnums(this.listQuery.platformName, this.listQuery.env).then(response => {
        if (response.code === '0000') {
          const data = response.data
          this.clientNameOptions = data.clientNameList
          this.serviceCategoryOptions = data.serviceCategoryList
          this.serviceNameOptions = data.serviceNameList
          this.envOptions = data.envList
          this.resultOptions = data.resultList
          this.rpcTypeOptions = data.rpcTypeList
          this.userInfoTypeOptions = data.userInfoTypeList
          if (this.listQuery.env === '') {
            this.listQuery.env = this.envOptions[0]
          }
        }
        this.listLoading = false
      })
    },
    handleQueryTraceInfo() {
      // 先控制隐藏显示时序图按钮,等查询完成后再按需显示
      this.isSingleTrace = false
      if (this.listQuery.traceId !== '') {
        this.listQuery.pageNum = 1
        this.listQuery.pageSize = 100
      }
      this.listQuery.fromDate = (this.dateRange === undefined || this.dateRange === null) ? '' : this.dateRange[0]
      this.listQuery.toDate = (this.dateRange === undefined || this.dateRange === null) ? '' : this.dateRange[1]

      this.listLoading = true
      queryTraceInfo(this.listQuery).then(response => {
        if (response.code === '0000') {
          this.data = response.data
          this.total = response.page.totalCount
          this.isSingleTrace = this.listQuery.traceId !== ''
        }
        this.listLoading = false
      })
    },
    handleRowClick(row) {
      this.listQuery.traceId = row.traceId
    },
    displayParametersJson(row) {
      this.paramsVisible = true
      this.parameterInJson = row.requestJson
      this.parameterOutJson = row.responseJson
    },
    displayJavaLog(row) {
      this.listLoading = true
      this.logTraceTableTitle = 'traceId:[' + row.traceId + '-' + row.rpcId + ']相关Java日志'
      queryJavaLog({
        traceId: row.traceId,
        rpcId: row.rpcId
      }).then(response => {
        if (response.code === '0000') {
          this.logTraceData = response.data
        }
        this.logTraceVisible = true
        this.listLoading = false
      })
    },
    message(row) {
      this.$message.info(row.runTime + '')
    },
    calTrafficSize(row) {
      const trafficSize = row.requestSize + row.responseSize
      let unit = ''
      let size = 0
      if (trafficSize > (1024 * 1024)) {
        size = (trafficSize / (1024 * 1024)).toFixed(1)
        unit = 'MB'
      } else if (trafficSize > 1024) {
        size = (trafficSize / 1024).toFixed(1)
        unit = 'KB'
      } else {
        size = '-'
      }
      return size + unit
    },
    handlePageChange(data) {
      this.listQuery.pageNum = data.page
      this.listQuery.pageSize = data.limit
      this.handleQueryTraceInfo()
    },
    handleClearTraceId() {
      this.listQuery.pageNum = 1
      this.listQuery.pageSize = 10
    },
    displaySequence() {
      this.$refs.diagramContainer.style.display = 'block'
      this.$refs.diagram.innerHTML = ''
      const treeData = treeToArray(this.data, true)
      let sequenceStr = ''
      for (let i = 0; i < treeData.length; i++) {
        const traceInfoObject = treeData[i]
        if (traceInfoObject.clientName != '' && traceInfoObject.clientName != null) {
          var seq_client = traceInfoObject.clientName.replace(new RegExp(/(-)/g), '_').replace('_ice', '')
          var seq_service = traceInfoObject.serviceCategory.replace('IceService', '')
          if (seq_service.indexOf('ProductManager') > -1) {
            seq_service = 'product'
          } else if (seq_service.indexOf('AasAccounting') > -1) {
            seq_service = 'account'
          } else if (seq_service.indexOf('MarketingAcitvitie') > -1) {
            seq_service = 'marketing'
          }
          seq_service = seq_service.toLowerCase().replace(new RegExp(/(-)/g), '_').replace('csc', 'csc_')
          sequenceStr += seq_client + '->' + seq_service + ': ' + '[' + traceInfoObject.rpcId + ']' + traceInfoObject.methodName + '[' + traceInfoObject.runTime + 'ms]'

          if (traceInfoObject.result != 'OK') {
            sequenceStr += '(ERROR)'
          }
          sequenceStr += '\n'
        }
      }
      const diagram = Diagram.parse(sequenceStr)
      diagram.drawSVG('diagram', { theme: 'simple' })
    },
    handleCloseDiagram() {
      this.$refs.diagramContainer.style.display = 'none'
    }

  }
}
</script>
<style>

  .tag{
    height: 24px;
    padding: 0 5px;
    line-height: 22px;
    box-sizing: border-box;
    border: 1px solid rgba(64,158,255,.2);
    white-space: nowrap;
    font-size: 12px;
  }

  .app-container .el-form-item {
    margin-bottom: 0px;
  }
  .app-container .pagination-container{
    margin-top: 0px;
    text-align: center;
  }
  .drop-checkbox {
    display: block;
    width: 120px;
    margin-left: 15px !important;
  }
  #diagram{
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    width: 80%;
    height: 80%;
    background: #fff;
    overflow: auto
  }
  #diagram:before{
    position: absolute;
    top: 15px;
    right: 15px;
    content: 'x';
    color: #000;
  }
  .diagramContainer{
    cursor: pointer;
    position: fixed;
    top: 0;
    left: 0;
    z-index: 100;
    height: 100%;
    width: 100%;
    background: rgba(0, 0, 0, 0.7);
    display: none;
  }
</style>

